package net.sourceforge.peers.sip.core.useragent;

import java.net.SocketException;
import java.util.ArrayList;

import net.sourceforge.peers.sip.RFC3261;
import net.sourceforge.peers.sip.syntaxencoding.SipHeaderFieldName;
import net.sourceforge.peers.sip.syntaxencoding.SipHeaderFieldValue;
import net.sourceforge.peers.sip.syntaxencoding.SipHeaderParamName;
import net.sourceforge.peers.sip.syntaxencoding.SipHeaders;
import net.sourceforge.peers.sip.transaction.TransactionManager;
import net.sourceforge.peers.sip.transactionuser.Dialog;
import net.sourceforge.peers.sip.transactionuser.DialogManager;
import net.sourceforge.peers.sip.transport.SipMessage;
import net.sourceforge.peers.sip.transport.SipRequest;
import net.sourceforge.peers.sip.transport.SipResponse;
import net.sourceforge.peers.sip.transport.SipServerTransportUser;
import net.sourceforge.peers.sip.transport.TransportManager;

public class UAS implements SipServerTransportUser {

    public final static ArrayList<String> SUPPORTED_METHODS;

    static {
        SUPPORTED_METHODS = new ArrayList<>();
        SUPPORTED_METHODS.add(RFC3261.METHOD_INVITE);
        SUPPORTED_METHODS.add(RFC3261.METHOD_ACK);
        SUPPORTED_METHODS.add(RFC3261.METHOD_CANCEL);
        SUPPORTED_METHODS.add(RFC3261.METHOD_OPTIONS);
        SUPPORTED_METHODS.add(RFC3261.METHOD_BYE);

    }

    private final InitialRequestManager initialRequestManager;
    private final MidDialogRequestManager midDialogRequestManager;

    private final DialogManager dialogManager;

    /**
     * should be instanciated only once, it was a singleton.
     */
    public UAS(UserAgent userAgent, InitialRequestManager initialRequestManager, MidDialogRequestManager midDialogRequestManager, DialogManager dialogManager, TransactionManager transactionManager, TransportManager transportManager) throws SocketException {
        this.initialRequestManager = initialRequestManager;
        this.midDialogRequestManager = midDialogRequestManager;
        this.dialogManager = dialogManager;
        transportManager.setSipServerTransportUser(this);
        transportManager.createServerTransport(RFC3261.TRANSPORT_UDP, userAgent.getConfig().getSipPort());
    }

    @Override
    //接受消息  根据接受的消息为请求还是响应调用不同的方法
    public void messageReceived(SipMessage sipMessage) {
        if (sipMessage instanceof SipRequest) {
            requestReceived((SipRequest) sipMessage);
        } else if (sipMessage instanceof SipResponse) {
            responseReceived((SipResponse) sipMessage);
        } else {
            throw new RuntimeException("unknown message type");
        }
    }

    private void responseReceived(SipResponse sipResponse) {

    }

    private void requestReceived(SipRequest sipRequest) {
        SipHeaders headers = sipRequest.getSipHeaders();

        //查找请求是否在现有会话中
        SipHeaderFieldValue to = headers.get(new SipHeaderFieldName(RFC3261.HDR_TO));
        String toTag = to.getParam(new SipHeaderParamName(RFC3261.PARAM_TAG));
        if (toTag != null) {
            Dialog dialog = dialogManager.getDialog(sipRequest);
            if (dialog != null) {
                //this is a mid-dialog request
                midDialogRequestManager.manageMidDialogRequest(sipRequest, dialog);
            }

        } else {
            //此请求不在当前会话中可能是 invite请求  cancel请求
            initialRequestManager.manageInitialRequest(sipRequest);
        }
    }

    void acceptCall(SipRequest sipRequest, Dialog dialog) {
        initialRequestManager.getInviteHandler().acceptCall(sipRequest, dialog);
    }

    void rejectCall(SipRequest sipRequest) {
        initialRequestManager.getInviteHandler().rejectCall(sipRequest);
    }

}
